package com.pangu.core.engine.game;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.pangu.core.BMDataContext;
import com.pangu.core.cache.CacheHelper;
import com.pangu.core.engine.game.state.GameEvent;
import com.pangu.core.nettyserver.client.NettyClients;
import com.pangu.core.nettyserver.handler.BeiMiClient;
import com.pangu.util.GameUtils;
import com.pangu.util.RandomCharUtil;
import com.pangu.util.UKTools;
import com.pangu.util.disruptor.DisruptorHandler;
import com.pangu.util.rules.model.Board;
import com.pangu.util.rules.model.JoinRoom;
import com.pangu.util.rules.model.Player;
import com.pangu.util.rules.model.RecoveryData;
import com.pangu.web.model.GamePlayway;
import com.pangu.web.model.GameRoom;
import com.pangu.web.model.PlayUserClient;
import com.pangu.web.service.repository.jpa.GameRoomRepository;

/**
 * 
 * Description:重写sangong游戏引擎
 *
 * @author abo
 * @date 2018年3月27日
 */
@Service(value="sangongGameEngine")
public class SangongGameEngine {
	public void gameRequest(String userid, String playway, String room, String orgi, PlayUserClient userClient,
			BeiMiClient beiMiClient) {
		GameEvent gameEvent = gameRequest(userClient.getId(), beiMiClient.getPlayway(), beiMiClient,
				beiMiClient.getOrgi(), userClient);
		if (gameEvent != null) {
			/**
			 * 举手了，表示游戏可以开始了
			 */
			if (userClient != null) {
				userClient.setGamestatus(BMDataContext.GameStatusEnum.READY.toString());
			}

			/**
			 * 游戏状态 ， 玩家请求 游戏房间，活动房间状态后，发送事件给 StateMachine，由 StateMachine驱动 游戏状态 ，
			 * 此处只负责通知房间内的玩家 1、有新的玩家加入
			 * 2、给当前新加入的玩家发送房间中所有玩家信息（不包含隐私信息，根据业务需求，修改PlayUserClient的字段，剔除掉隐私信息后发送）
			 */
			ActionTaskUtils.sendEvent("joinroom", new JoinRoom(userClient, gameEvent.getIndex(),
					gameEvent.getGameRoom().getPlayers(), gameEvent.getGameRoom()), gameEvent.getGameRoom());
			/**
			 * 发送给单一玩家的消息
			 */
			ActionTaskUtils.sendPlayers(beiMiClient, gameEvent.getGameRoom());

			
			/**
			 * 当前是在游戏中还是 未开始
			 */
			// Board board = (Board)
			// CacheHelper.getBoardCacheBean().getCacheObject(gameEvent.getRoomid(),
			// gameEvent.getOrgi());
			// if (board != null) {
			// Player currentPlayer = null;
			// for (Player player : board.getPlayers()) {
			// if (player.getPlayuser().equals(userClient.getId())) {
			// currentPlayer = player;
			// break;
			// }
			// }
			// if (currentPlayer != null) {
			// boolean automic = false;
			// if ((board.getLast() != null &&
			// board.getLast().getUserid().equals(currentPlayer.getPlayuser()))
			// || (board.getLast() == null &&
			// board.getBanker().equals(currentPlayer.getPlayuser()))) {
			// automic = true;
			// }
			// ActionTaskUtils.sendEvent("recovery",
			// new RecoveryData(currentPlayer, board.getLasthands(),
			// board.getNextplayer() != null ? board.getNextplayer().getNextplayer() : null,
			// 25,
			// automic, board),
			// gameEvent.getGameRoom());
			// }
			// } else {
			// 通知状态 此处应由状态机处理异步执行
			GameUtils.getGame(beiMiClient.getPlayway(), gameEvent.getOrgi()).change(gameEvent);
			// }
		}
	}

	/**
	 * 玩家房间选择， 新请求，游戏撮合， 如果当前玩家是断线重连， 或者是 退出后进入的，则第一步检查是否已在房间 如果已在房间，直接返回
	 * 
	 * @param userid
	 * @param orgi
	 * @return
	 */
	public GameEvent gameRequest(String userid, String playway, BeiMiClient beiMiClient, String orgi,
			PlayUserClient playUser) {
		GameEvent gameEvent = null;
		String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(userid, orgi);
		// 获取玩法
		GamePlayway gamePlayway = (GamePlayway) CacheHelper.getSystemCacheBean().getCacheObject(playway, orgi);
		boolean needtakequene = false;
		if (gamePlayway != null) {
			gameEvent = new GameEvent(gamePlayway.getPlayers(), gamePlayway.getCardsnum(), orgi);
			GameRoom gameRoom = null;
			if (!StringUtils.isBlank(roomid)
					&& CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) != null) {//
				gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi);
				// 直接加入到 系统缓存 （只有一个地方对GameRoom进行二次写入，避免分布式锁）
			} else {
				// if (beiMiClient.getExtparams() != null
				// &&
				// BMDataContext.BEIMI_SYSTEM_ROOM.equals(beiMiClient.getExtparams().get("gamemodel")))
				// {
				// // 房卡游戏 , 创建ROOM
				// gameRoom = this.creatGameRoom(gamePlayway, userid, true, beiMiClient);
				// } else {

				// 大厅游戏 ， 撮合游戏 , 发送异步消息，通知RingBuffer进行游戏撮合，撮合算法描述如下： 1、按照查找
				// gameRoom = (GameRoom) CacheHelper.getQueneCache().poll(playway, orgi);
				// if (gameRoom != null) {
				// /**
				// * 修正获取gameroom获取的问题，因为删除房间的时候，为了不损失性能，没有将 队列里的房间信息删除，如果有玩家获取到这个垃圾信息
				// * 则立即进行重新获取房价，
				// */
				// while (CacheHelper.getGameRoomCacheBean().getCacheObject(gameRoom.getId(),
				// gameRoom.getOrgi()) == null) {
				// gameRoom = (GameRoom) CacheHelper.getQueneCache().poll(playway, orgi);
				// if (gameRoom == null) {
				// break;
				// }
				// }
				// }

				// if (gameRoom == null) { // 无房间 ， 需要
				gameRoom = this.creatGameRoom(gamePlayway, userid, false, beiMiClient);
				// } else {
				// playUser.setPlayerindex(System.currentTimeMillis());// 从后往前坐，房主进入以后优先坐在 首位
				// needtakequene = true;
				// }
				// }
			}
			if (gameRoom != null) {
				/**
				 * 设置游戏当前已经进行的局数
				 */
				gameRoom.setCurrentnum(0);
				/**
				 * 更新缓存
				 */
				CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, orgi);
				/**
				 * 如果当前房间到达了最大玩家数量，则不再加入到 撮合队列
				 */
				List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(),
						gameRoom.getOrgi());
//				if (playerList.size() == 0) {
					gameEvent.setEvent(BeiMiGameEvent.ENTER.toString());//？？？？？？
//				} else {
//					gameEvent.setEvent(BeiMiGameEvent.JOIN.toString());
//				}
				gameEvent.setGameRoom(gameRoom);
				gameEvent.setRoomid(gameRoom.getId());

				/**
				 * 无条件加入房间
				 */
				this.joinRoom(gameRoom, playUser, playerList);

				for (PlayUserClient temp : playerList) {
					if (temp.getId().equals(playUser.getId())) {
						gameEvent.setIndex(playerList.indexOf(temp));
						break;
					}
				}
				/**
				 * 如果当前房间到达了最大玩家数量，则不再加入到 撮合队列
				 */
				if (playerList.size() < gamePlayway.getPlayers() && needtakequene == true) {
					CacheHelper.getQueneCache().put(gameRoom, orgi); // 未达到最大玩家数量，加入到游戏撮合 队列，继续撮合
				}

			}
		}
		return gameEvent;
	}

	/**
	 * 
	 * Description: 创建新房间 ，需要传入房间的玩法 ， 玩法定义在 系统运营后台，玩法创建后，放入系统缓存 ， 客户端进入房间的时候，传入
	 * 玩法ID参数
	 * 
	 * @author abo
	 * @date 2018年3月27日
	 * @param playway
	 * @param userid
	 * @param cardroom
	 * @param beiMiClient
	 * @return
	 */
	private GameRoom creatGameRoom(GamePlayway playway, String userid, boolean cardroom, BeiMiClient beiMiClient) {
		GameRoom gameRoom = new GameRoom();
		gameRoom.setCreatetime(new Date());
		gameRoom.setRoomid(UKTools.getUUID());
		gameRoom.setUpdatetime(new Date());
		// 玩法不等于空的时候
		if (playway != null) {
			gameRoom.setPlayway(playway.getId());
			gameRoom.setRoomtype(playway.getRoomtype());
			gameRoom.setPlayers(playway.getPlayers());
		}
		gameRoom.setPlayers(playway.getPlayers());
		gameRoom.setCardsnum(playway.getCardsnum());

		gameRoom.setCurpalyers(1);
		gameRoom.setCardroom(cardroom);

		gameRoom.setStatus(BeiMiGameEnum.CRERATED.toString());

		gameRoom.setCardsnum(playway.getCardsnum());

		gameRoom.setCurrentnum(0);

		gameRoom.setCreater(userid);

		gameRoom.setMaster(userid);
		gameRoom.setNumofgames(playway.getNumofgames()); // 无限制
		gameRoom.setOrgi(playway.getOrgi());

		//
		//
		// //房卡模式启动游戏
		// if (beiMiClient.getExtparams() != null
		// &&
		// BMDataContext.BEIMI_SYSTEM_ROOM.equals(beiMiClient.getExtparams().get("gamemodel")))
		// {
		// gameRoom.setRoomtype(BMDataContext.ModelType.ROOM.toString());
		// gameRoom.setCardroom(true);
		// gameRoom.setExtparams(beiMiClient.getExtparams());
		// /**
		// * 产生 房间 ID ， 麻烦的是需要处理冲突 ，准备采用的算法是 先生成一个号码池子，然后重分布是缓存的 Queue里获取
		// */
		// gameRoom.setRoomid(RandomCharUtil.getRandomNumberChar(6));
		//
		// /**
		// * 分配房间号码 ， 并且，启用 规则引擎，对房间信息进行赋值
		// */
		// kieSession.insert(gameRoom);
		// kieSession.fireAllRules();
		// } else {
		gameRoom.setRoomtype(BMDataContext.ModelType.HALL.toString());
		// }

		CacheHelper.getQueneCache().put(gameRoom, playway.getOrgi()); // 未达到最大玩家数量，加入到游戏撮合 队列，继续撮合

		DisruptorHandler.published(gameRoom, null, BMDataContext.getContext().getBean(GameRoomRepository.class),
				BMDataContext.UserDataEventType.SAVE.toString());

		return gameRoom;
	}

	/**
	 * 
	 * Description: 玩家加入房间
	 * 
	 * @author abo
	 * @date 2018年3月27日
	 * @param gameRoom
	 * @param playUser
	 * @param playerList
	 */
	public void joinRoom(GameRoom gameRoom, PlayUserClient playUser, List<PlayUserClient> playerList) {
		boolean inroom = false;
		for (PlayUserClient user : playerList) {
			if (user.getId().equals(playUser.getId())) {
				inroom = true;
				break;
			}
		}
		if (inroom == false) {
			playUser.setPlayerindex(System.currentTimeMillis());
			playUser.setGamestatus(BMDataContext.GameStatusEnum.READY.toString());
			playUser.setPlayertype(BMDataContext.PlayerTypeEnum.NORMAL.toString());
			playUser.setRoomid(gameRoom.getId());
			playUser.setRoomready(false);

			playerList.add(playUser);
			NettyClients.getInstance().joinRoom(playUser.getId(), gameRoom.getId());
			// 将用户加入到 room MultiCache
			CacheHelper.getGamePlayerCacheBean().put(playUser.getId(), playUser, playUser.getOrgi());
		}

		/**
		 * 不管状态如何，玩家一定会加入到这个房间
		 */
		CacheHelper.getRoomMappingCacheBean().put(playUser.getId(), gameRoom.getId(), playUser.getOrgi());
	}
}
